package models

import (
	"encoding/json"
	"fmt"
	"math"
	"time"
)

// PricingEngine 定价引擎
type PricingEngine struct {
	BasePricing *VenuePricing
	Rules       []PricingRule
}

// VenuePricing 场地定价结构
type VenuePricing struct {
	BasePrice       float64                 `json:"base_price"`
	TimeSlots       map[string]TimeSlotRate `json:"time_slots"`
	WeekdayFactors  map[int]float64         `json:"weekday_factors"`
	HolidayFactors  map[string]float64      `json:"holiday_factors"`
	DemandFactors   map[string]float64      `json:"demand_factors"`
	MemberDiscounts map[int]float64         `json:"member_discounts"`
}

// TimeSlotRate 时段费率
type TimeSlotRate struct {
	StartTime string  `json:"start_time"`
	EndTime   string  `json:"end_time"`
	Rate      float64 `json:"rate"`
	Type      string  `json:"type"` // morning, afternoon, evening, night
}

// PricingRule 定价规则
type PricingRule struct {
	Type        string      `json:"type"` // weekday, holiday, demand, member
	Condition   string      `json:"condition"`
	Factor      float64     `json:"factor"`
	Description string      `json:"description"`
	Priority    int         `json:"priority"`
	Active      bool        `json:"active"`
	Parameters  interface{} `json:"parameters"`
}

// PriceRequest 价格计算请求
type PriceRequest struct {
	VenueID     int64   `json:"venue_id"`
	StartTime   int64   `json:"start_time"`
	EndTime     int64   `json:"end_time"`
	MemberID    int64   `json:"member_id"`
	MemberLevel int     `json:"member_level"`
	BookingDate string  `json:"booking_date"`
	Occupancy   float64 `json:"occupancy"` // 场地占用率
	Weather     string  `json:"weather"`
	Special     bool    `json:"special"`
}

// PriceResponse 价格计算响应
type PriceResponse struct {
	BasePrice      float64              `json:"base_price"`
	OriginalPrice  float64              `json:"original_price"`
	FinalPrice     float64              `json:"final_price"`
	DiscountAmount float64              `json:"discount_amount"`
	Breakdown      []PriceBreakdown     `json:"breakdown"`
	AppliedRules   []AppliedPricingRule `json:"applied_rules"`
}

// PriceBreakdown 价格明细
type PriceBreakdown struct {
	Type        string  `json:"type"`
	Description string  `json:"description"`
	Amount      float64 `json:"amount"`
	Factor      float64 `json:"factor"`
}

// AppliedPricingRule 应用的价格规则
type AppliedPricingRule struct {
	RuleID      string  `json:"rule_id"`
	Type        string  `json:"type"`
	Description string  `json:"description"`
	Discount    float64 `json:"discount"`
}

// NewPricingEngine 创建新的定价引擎
func NewPricingEngine(venue *Venue) *PricingEngine {
	engine := &PricingEngine{
		BasePricing: loadVenuePricing(venue),
		Rules:       loadPricingRules(),
	}
	return engine
}

// CalculatePrice 计算最终价格
func (pe *PricingEngine) CalculatePrice(req *PriceRequest) (*PriceResponse, error) {
	response := &PriceResponse{
		Breakdown:    []PriceBreakdown{},
		AppliedRules: []AppliedPricingRule{},
	}

	// 计算基础价格
	basePrice := pe.calculateBasePrice(req)
	response.BasePrice = basePrice
	response.OriginalPrice = basePrice

	// 应用定价规则
	finalPrice := basePrice
	appliedRules := []AppliedPricingRule{}

	// 按优先级排序规则
	sortedRules := pe.sortRulesByPriority()

	for _, rule := range sortedRules {
		if !rule.Active {
			continue
		}

		if pe.evaluateRuleCondition(rule, req) {
			discount := pe.applyRule(rule, finalPrice)
			finalPrice -= discount

			appliedRules = append(appliedRules, AppliedPricingRule{
				RuleID:      rule.Type,
				Type:        rule.Type,
				Description: rule.Description,
				Discount:    discount,
			})

			response.Breakdown = append(response.Breakdown, PriceBreakdown{
				Type:        rule.Type,
				Description: rule.Description,
				Amount:      -discount,
				Factor:      rule.Factor,
			})
		}
	}

	response.FinalPrice = math.Max(0, finalPrice)
	response.DiscountAmount = response.OriginalPrice - response.FinalPrice
	response.AppliedRules = appliedRules

	return response, nil
}

// calculateBasePrice 计算基础价格
func (pe *PricingEngine) calculateBasePrice(req *PriceRequest) float64 {
	duration := float64(req.EndTime-req.StartTime) / 3600.0 // 转换为小时

	// 获取时段费率
	timeSlotRate := pe.getTimeSlotRate(req.StartTime, req.EndTime)

	// 基础价格 = 时长 * 时段费率
	basePrice := duration * pe.BasePricing.BasePrice * timeSlotRate

	return basePrice
}

// getTimeSlotRate 获取时段费率
func (pe *PricingEngine) getTimeSlotRate(startTime, endTime int64) float64 {
	startHour := time.Unix(startTime, 0).Hour()

	// 默认费率
	defaultRate := 1.0

	// 根据时间段匹配费率
	for _, slot := range pe.BasePricing.TimeSlots {
		startSlot := parseHour(slot.StartTime)
		endSlot := parseHour(slot.EndTime)

		if startHour >= startSlot && startHour < endSlot {
			return slot.Rate
		}
	}

	return defaultRate
}

// evaluateRuleCondition 评估规则条件
func (pe *PricingEngine) evaluateRuleCondition(rule PricingRule, req *PriceRequest) bool {
	switch rule.Type {
	case "weekday":
		return pe.evaluateWeekdayRule(rule, req)
	case "holiday":
		return pe.evaluateHolidayRule(rule, req)
	case "demand":
		return pe.evaluateDemandRule(rule, req)
	case "member":
		return pe.evaluateMemberRule(rule, req)
	case "weather":
		return pe.evaluateWeatherRule(rule, req)
	case "special":
		return pe.evaluateSpecialRule(rule, req)
	default:
		return false
	}
}

// evaluateWeekdayRule 评估工作日规则
func (pe *PricingEngine) evaluateWeekdayRule(rule PricingRule, req *PriceRequest) bool {
	weekday := time.Unix(req.StartTime, 0).Weekday()
	factor, exists := pe.BasePricing.WeekdayFactors[int(weekday)]
	return exists && factor > 0
}

// evaluateHolidayRule 评估节假日规则
func (pe *PricingEngine) evaluateHolidayRule(rule PricingRule, req *PriceRequest) bool {
	date := time.Unix(req.StartTime, 0).Format("2006-01-02")
	factor, exists := pe.BasePricing.HolidayFactors[date]
	return exists && factor > 0
}

// evaluateDemandRule 评估需求规则
func (pe *PricingEngine) evaluateDemandRule(rule PricingRule, req *PriceRequest) bool {
	return req.Occupancy > 0.8 // 占用率大于80%时触发
}

// evaluateMemberRule 评估会员规则
func (pe *PricingEngine) evaluateMemberRule(rule PricingRule, req *PriceRequest) bool {
	return req.MemberID > 0 && req.MemberLevel > 0
}

// evaluateWeatherRule 评估天气规则
func (pe *PricingEngine) evaluateWeatherRule(rule PricingRule, req *PriceRequest) bool {
	if req.Weather == "" {
		return false
	}

	weatherFactors := map[string]float64{
		"rainy":  0.95, // 雨天降价5%
		"snowy":  0.90, // 雪天降价10%
		"stormy": 0.85, // 暴风雨降价15%
	}

	factor, exists := weatherFactors[req.Weather]
	return exists && factor > 0
}

// evaluateSpecialRule 评估特殊规则
func (pe *PricingEngine) evaluateSpecialRule(rule PricingRule, req *PriceRequest) bool {
	return req.Special
}

// applyRule 应用规则计算折扣
func (pe *PricingEngine) applyRule(rule PricingRule, currentPrice float64) float64 {
	switch rule.Type {
	case "member":
		return pe.applyMemberDiscount(currentPrice, int(rule.Factor))
	case "weekday", "holiday", "demand", "weather", "special":
		return currentPrice * (1 - rule.Factor)
	default:
		return 0
	}
}

// applyMemberDiscount 应用会员折扣
func (pe *PricingEngine) applyMemberDiscount(price float64, memberLevel int) float64 {
	discountFactor := 1.0

	switch memberLevel {
	case 1: // 普通会员
		discountFactor = 0.95
	case 2: // 白银会员
		discountFactor = 0.90
	case 3: // 黄金会员
		discountFactor = 0.85
	case 4: // 钻石会员
		discountFactor = 0.80
	}

	return price * (1 - discountFactor)
}

// sortRulesByPriority 按优先级排序规则
func (pe *PricingEngine) sortRulesByPriority() []PricingRule {
	// 实现排序逻辑
	return pe.Rules
}

// loadVenuePricing 加载场地定价配置
func loadVenuePricing(venue *Venue) *VenuePricing {
	pricing := &VenuePricing{
		BasePrice: venue.HourPrice,
		TimeSlots: map[string]TimeSlotRate{
			"morning":   {StartTime: "09:00", EndTime: "12:00", Rate: 0.8},
			"afternoon": {StartTime: "12:00", EndTime: "18:00", Rate: 1.0},
			"evening":   {StartTime: "18:00", EndTime: "24:00", Rate: 1.2},
			"night":     {StartTime: "00:00", EndTime: "09:00", Rate: 0.6},
		},
		WeekdayFactors: map[int]float64{
			1: 1.0, // 周一
			2: 1.0, // 周二
			3: 1.0, // 周三
			4: 1.0, // 周四
			5: 1.2, // 周五
			6: 1.5, // 周六
			0: 1.5, // 周日
		},
		HolidayFactors: map[string]float64{
			"2025-01-01": 2.0, // 元旦
			"2025-02-14": 1.8, // 情人节
			"2025-10-01": 2.0, // 国庆节
		},
		DemandFactors: map[string]float64{
			"high": 1.1,
			"low":  0.9,
		},
		MemberDiscounts: map[int]float64{
			1: 0.95,
			2: 0.90,
			3: 0.85,
			4: 0.80,
		},
	}

	// 如果场地有分时段定价，加载自定义配置
	if venue.TimeBasedPricing != "" {
		var timeBasedPricing map[string]TimeSlotRate
		if err := json.Unmarshal([]byte(venue.TimeBasedPricing), &timeBasedPricing); err == nil {
			pricing.TimeSlots = timeBasedPricing
		}
	}

	return pricing
}

// loadPricingRules 加载定价规则
func loadPricingRules() []PricingRule {
	return []PricingRule{
		{
			Type:        "weekday",
			Condition:   "weekend",
			Factor:      1.5,
			Description: "周末价格上浮50%",
			Priority:    1,
			Active:      true,
		},
		{
			Type:        "holiday",
			Condition:   "national_holiday",
			Factor:      2.0,
			Description: "节假日价格上浮100%",
			Priority:    2,
			Active:      true,
		},
		{
			Type:        "demand",
			Condition:   "occupancy>80%",
			Factor:      1.1,
			Description: "高需求时段价格上浮10%",
			Priority:    3,
			Active:      true,
		},
		{
			Type:        "member",
			Condition:   "member_level",
			Factor:      0.0, // 会员折扣在applyMemberDiscount中处理
			Description: "会员折扣",
			Priority:    4,
			Active:      true,
		},
		{
			Type:        "weather",
			Condition:   "rainy",
			Factor:      0.95,
			Description: "雨天价格下调5%",
			Priority:    5,
			Active:      true,
		},
	}
}

// parseHour 解析时间字符串为小时
func parseHour(timeStr string) int {
	var hour int
	fmt.Sscanf(timeStr, "%d:%*d", &hour)
	return hour
}

// GetPriceForBooking 为预约计算价格
func GetPriceForBooking(venue *Venue, req *PriceRequest) (*PriceResponse, error) {
	engine := NewPricingEngine(venue)
	return engine.CalculatePrice(req)
}
